﻿using System;
using System.Collections.Concurrent;
using System.Linq;

using Common.Base;

using CommunicationLibrary;
using CommunicationLibrary.TransportData;

using GameNetwork.Interfaces;

namespace GameNetwork.Network
{
    internal class NetworkClient : IClient, INetworkClient
    {
        private readonly ConcurrentDictionary<DateTime, GameState> gameStates;

        private GameState currentGameState;
        
        public NetworkClient()
        {
            this.gameStates = new ConcurrentDictionary<DateTime, GameState>();
        }
        
        public event NetworkGameStartedEventHandler OnGameStarted;

        public event NetworkGameReadyEventHandler OnGameReady;

        public event NetworkGameWonEventHandler OnGameWon;

        public event NetworkGameLostEventHandler OnGameLost;

        public event NetworkConnectionErrorEventHandler OnConnectionError;

        public void GameStarted()
        {
            if (this.OnGameStarted != null)
            {
                this.OnGameStarted();
            }
        }

        public void HasWon()
        {
            if (this.OnGameWon != null)
            {
                this.OnGameWon();
            }
        }

        public void PlayerLost(Identifiable looser)
        {
            if (this.OnGameLost != null)
            {
                this.OnGameLost(looser.Identifier);
            }
        }

        public void GamePaused()
        {
            throw new NotImplementedException();
        }

        public void GameResumed()
        {
            throw new NotImplementedException();
        }

        public void UpdateGameState(GameState gameState)
        {
            this.gameStates.AddOrUpdate(DateTime.Now, gameState, (time, state) => gameState);
        }

        public void GameReady(GameState startingState, int identifier)
        {
            this.gameStates.AddOrUpdate(DateTime.Now, startingState, (time, state) => startingState);

            if (this.OnGameReady != null)
            {
                this.OnGameReady(startingState, identifier);
            }
        }

        public GameState GetCurrentGameState()
        {
            if (!this.gameStates.Any())
            {
                return this.currentGameState;
            }

            this.currentGameState = this.gameStates.Last().Value;
            this.gameStates.Clear();

            return this.currentGameState;
        }

        public IClient GetClient()
        {
            return this;
        }

        public void ClearGameStates()
        {
            this.gameStates.Clear();
            this.currentGameState = null;
        }
    }
}